//package cn.dansj.test;
//
//import cn.dansj.common.context.ApplicationContextProvider;
//import cn.dansj.common.jdbc.DBUtils;
//import cn.dansj.common.jdbc.jdbcTemplate.JdbcTemplate;
//import cn.dansj.common.utils.bean.DBConnection;
//import cn.dansj.common.utils.enums.DbType;
//import cn.dansj.common.utils.lock.AbstractLock;
//import cn.dansj.common.utils.lock.LockException;
//import cn.dansj.common.utils.transfer.AssertUtils;
//import cn.dansj.common.utils.transfer.Transformation;
//import org.springframework.jdbc.datasource.DataSourceUtils;
//
//import javax.sql.DataSource;
//import java.sql.Connection;
//import java.sql.SQLException;
//import java.util.Map;
//
///**
// * 数据库分布式锁实现
// */
//public class DatabaseLock extends AbstractLock {
//    private final String lockName;
//    private boolean isLocked = false;
//    private final long tryLockWaitMs;
//    private final long lockExpireMs;
//
//    private final JdbcTemplate jdbcTemplate;
//
//    private final String createTableSql;
//    private static final String insertLockSql = "INSERT INTO x_distributed_locks (lock_name, lock_owner, expire_time, lock_time)  SELECT ?, ?, ?, ? from dual ";
//    private static final String unlockSql = "DELETE FROM x_distributed_locks WHERE lock_name = ? AND lock_owner = ?";
//    private static final String checkSql = "SELECT 1 FROM x_distributed_locks";
//    private static final String updateLockSql = "UPDATE x_distributed_locks  SET lock_owner = ?, expire_time = ?  WHERE lock_name = ? AND  expire_time < ?";
//    private static final Map<DbType, String> createTableSqlMap = Map.of(DbType.mysql, "CREATE TABLE x_distributed_locks (lock_name VARCHAR(255) PRIMARY KEY, lock_owner VARCHAR(255), expire_time bigint, lock_time bigint)",
//            DbType.oracle, "CREATE TABLE x_distributed_locks (lock_name VARCHAR2(255) PRIMARY KEY, lock_owner VARCHAR2(255), expire_time int, lock_time int)");
//
//    /**
//     * 构造函数
//     *
//     * @param lockName 锁名称
//     */
//    public DatabaseLock(DBConnection dbConnection, String lockName, long tryLockWaitMs, long lockExpireMs, boolean autoLock) {
//        super(lockName, tryLockWaitMs, lockExpireMs);
//        jdbcTemplate = dbConnection != null ? DBUtils.createJdbcTemplate(dbConnection) : ApplicationContextProvider.getBean(JdbcTemplate.class);
//        this.lockName = lockName;
//        this.tryLockWaitMs = tryLockWaitMs;
//        this.lockExpireMs = lockExpireMs;
//
//        try {
//            DataSource dataSource = jdbcTemplate.getDataSource();
//            assert dataSource != null;
//            Connection connection = dataSource.getConnection();
//            String url = connection.getMetaData().getURL();
//            DbType dbType = DbType.getDbType(DBUtils.getDbType(url));
//            AssertUtils.notNull(dbType, "解析数据库类型失败:" + url);
//            DataSourceUtils.releaseConnection(connection, dataSource);
//            createTableSql = createTableSqlMap.get(dbType);
//            if (autoLock) AssertUtils.state(lock(), new LockException("获取锁失败:" + lockName));
//        } catch (SQLException sqlException) {
//            throw new RuntimeException(Transformation.getBaseException(sqlException));
//        }
//    }
//
//    public DatabaseLock(DBConnection dbConnection, String lockName, long tryLockWaitMs, long lockExpireMs) {
//        this(dbConnection, lockName, tryLockWaitMs, lockExpireMs, true);
//    }
//
//    public DatabaseLock(String url, String username, String password, String lockName, long tryLockWaitMs, long lockExpireMs) {
//        this(new DBConnection(url, username, password), lockName, tryLockWaitMs, lockExpireMs);
//    }
//
//    public DatabaseLock(String url, String username, String password, String lockName, long tryLockWaitMs, long lockExpireMs, boolean autoLock) {
//        this(new DBConnection(url, username, password), lockName, tryLockWaitMs, lockExpireMs, autoLock);
//    }
//
//    public DatabaseLock(String lockName, long tryLockWaitMs, long lockExpireMs) {
//        this(null, lockName, tryLockWaitMs, lockExpireMs);
//    }
//
//    @Override
//    public boolean lock() {
//        if (isLocked) {
//            return true; // 可重入锁
//        }
//
//        // 尝试获取锁
//        boolean acquired = tryLock();
//        if (acquired) {
//            isLocked = true;
//            return true;
//        }
//        return false;
//    }
//
//    public boolean tryLock() {
//        long startTime = System.currentTimeMillis();
//
//        boolean isSuccess;
//
//        do {
//            System.out.println(1);
//            try {
//                try {
//                    isSuccess = acquireLock();
//                }catch (Throwable e) {
//                    isSuccess = false;
//                }
//                if (tryLockWaitMs <= 0) {
//                    break;
//                }
//
//                long elapsed = System.currentTimeMillis() - startTime;
//                if (elapsed >= tryLockWaitMs) {
//                    break;
//                }
//                Thread.sleep(Math.min(100, tryLockWaitMs - elapsed));
//            } catch (InterruptedException e) {
//                Thread.currentThread().interrupt();
//                isSuccess = false;
//                break;
//            }
//        } while (!isSuccess);
//
//        if (!isSuccess) {
//            throw new LockException(String.format("You can't do it,because another has get the lock(%s).", lockName));
//        }
//
//        return true;
//    }
//
//    private boolean acquireLock() {
//        // 使用数据库特定的锁机制
//        // MySQL: SELECT GET_LOCK(?, ?)
//        // Oracle: DBMS_LOCK.REQUEST
//        // PostgreSQL: pg_try_advisory_lock
//        // SQL Server: sp_getapplock
//
//        // 通用处理方式，通过数据库表
//        // 先检查锁表是否存在，不存在则创建
//        createLockTableIfNotExists();
//
//        int affectedRows = jdbcTemplate.update(insertLockSql, lockName, Thread.currentThread().getName(), System.currentTimeMillis() + lockExpireMs, System.currentTimeMillis());
//
//        if (affectedRows > 0) {
//            // 成功获取锁
//            return true;
//        }
//
//        // 检查锁是否已过期
//        affectedRows = jdbcTemplate.update(updateLockSql, Thread.currentThread().getName(), System.currentTimeMillis() + lockExpireMs, lockName, System.currentTimeMillis());
//        return affectedRows > 0;
//    }
//
//    private void createLockTableIfNotExists() {
//        try {
//            jdbcTemplate.queryForMap(checkSql);
//        } catch (Exception exception) {
//            String message = Transformation.getBaseException(exception).getMessage();
//            boolean tableNotExist = Transformation.patternExist(message, "Table '(.*?)' doesn't exist") | Transformation.patternExist(message, "ORA-00942");
//            if (tableNotExist) {
//                // 可能是其他数据库，尝试不同的SQL语法
//                try {
//                    jdbcTemplate.update(createTableSql);
//                } catch (Exception ex) {
//                    // 如果还是失败，抛出原始异常
//                    throw new RuntimeException("Failed to create distributed lock table: " + lockName, exception);
//                }
//            }
//        }
//    }
//
//    @Override
//    public boolean unlock() {
//        if (!isLocked) {
//            return true;
//        }
//
//        try {
//            int affectedRows = jdbcTemplate.update(unlockSql, lockName, Thread.currentThread().getName());
//            isLocked = affectedRows <= 0;
//            return affectedRows > 0;
//        } catch (Exception e) {
//            return false;
//        }
//    }
//
//    @Override
//    public void close() {
//        unlock();
//    }
//}